#ifndef __UIMANAGER_H__
#define __UIMANAGER_H__

#pragma once

namespace DuiLib
{
    /////////////////////////////////////////////////////////////////////////////////////
    //

    class CControlUI;


    /////////////////////////////////////////////////////////////////////////////////////
    //

    typedef enum EVENTTYPE_UI
    {
        UIEVENT__FIRST = 1,
        UIEVENT__KEYBEGIN,
        UIEVENT_KEYDOWN,
        UIEVENT_KEYUP,
        UIEVENT_CHAR,
        UIEVENT_SYSKEY,
        UIEVENT__KEYEND,
        UIEVENT__MOUSEBEGIN,
        UIEVENT_MOUSEMOVE,
        UIEVENT_MOUSELEAVE,
        UIEVENT_MOUSEENTER,
        UIEVENT_MOUSEHOVER,
        UIEVENT_BUTTONDOWN,
        UIEVENT_BUTTONUP,
        UIEVENT_RBUTTONDOWN,
        UIEVENT_DBLCLICK,
        UIEVENT_CONTEXTMENU,
        UIEVENT_SCROLLWHEEL,
        UIEVENT__MOUSEEND,
        UIEVENT_KILLFOCUS,
        UIEVENT_SETFOCUS,
        UIEVENT_WINDOWSIZE,
        UIEVENT_SETCURSOR,
        UIEVENT_TIMER,
        UIEVENT_NOTIFY,
        UIEVENT_COMMAND,
        UIEVENT__LAST,
    };

    /////////////////////////////////////////////////////////////////////////////////////
    //

    // Flags for CControlUI::GetControlFlags()
    #define UIFLAG_TABSTOP       0x00000001
    #define UIFLAG_SETCURSOR     0x00000002
    #define UIFLAG_WANTRETURN    0x00000004

    // Flags for FindControl()
    #define UIFIND_ALL           0x00000000
    #define UIFIND_VISIBLE       0x00000001
    #define UIFIND_ENABLED       0x00000002
    #define UIFIND_HITTEST       0x00000004
    #define UIFIND_UPDATETEST    0x00000008
    #define UIFIND_TOP_FIRST     0x00000010
    #define UIFIND_ME_FIRST      0x80000000

    // Flags for the CDialogLayout stretching
    #define UISTRETCH_NEWGROUP   0x00000001
    #define UISTRETCH_NEWLINE    0x00000002
    #define UISTRETCH_MOVE_X     0x00000004
    #define UISTRETCH_MOVE_Y     0x00000008
    #define UISTRETCH_SIZE_X     0x00000010
    #define UISTRETCH_SIZE_Y     0x00000020

    // Flags used for controlling the paint
    #define UISTATE_FOCUSED      0x00000001
    #define UISTATE_SELECTED     0x00000002
    #define UISTATE_DISABLED     0x00000004
    #define UISTATE_HOT          0x00000008
    #define UISTATE_PUSHED       0x00000010
    #define UISTATE_READONLY     0x00000020
    #define UISTATE_CAPTURED     0x00000040



    /////////////////////////////////////////////////////////////////////////////////////
    //

    typedef struct DUILIB_API tagTFontInfo
    {
        HFONT hFont;
        CDuiString sFontName;
        int iSize;
        bool bBold;
        bool bUnderline;
        bool bItalic;
        TEXTMETRIC tm;
    } TFontInfo;

    typedef struct DUILIB_API tagTImageInfo
    {
        HBITMAP hBitmap;
        LPBYTE pBits;
        LPBYTE pSrcBits;
        int nX;
        int nY;
        bool bAlpha;
        bool bUseHSL;
        CDuiString sResType;
        DWORD dwMask;
    } TImageInfo;

    typedef struct DUILIB_API tagTDrawInfo
    {
        tagTDrawInfo();
        tagTDrawInfo(LPCTSTR lpsz);
        void Clear();
        CDuiString sDrawString;
        CDuiString sImageName;
        bool bLoaded;
        const TImageInfo* pImageInfo;
        RECT rcDestOffset;
        RECT rcBmpPart;
        RECT rcScale9;
        BYTE uFade;
        bool bHole;
        bool bTiledX;
        bool bTiledY;
    } TDrawInfo;

    typedef struct DUILIB_API tagTPercentInfo
    {
        double left;
        double top;
        double right;
        double bottom;
    } TPercentInfo;

    typedef struct DUILIB_API tagTResInfo
    {
        DWORD m_dwDefaultDisabledColor;
        DWORD m_dwDefaultFontColor;
        DWORD m_dwDefaultLinkFontColor;
        DWORD m_dwDefaultLinkHoverFontColor;
        DWORD m_dwDefaultSelectedBkColor;
        TFontInfo m_DefaultFontInfo;
        CDuiStringPtrMap m_CustomFonts;
        CDuiStringPtrMap m_ImageHash;
        CDuiStringPtrMap m_AttrHash;
        CDuiStringPtrMap m_MultiLanguageHash;
    } TResInfo;

    // Structure for notifications from the system
    // to the control implementation.
    typedef struct DUILIB_API tagTEventUI
    {
        int Type;
        CControlUI* pSender;
        DWORD dwTimestamp;
        POINT ptMouse;
        TCHAR chKey;
        WORD wKeyState;
        WPARAM wParam;
        LPARAM lParam;
    } TEventUI;

    // Listener interface
    class DUILIB_API INotifyUI
    {
    public:
        virtual void Notify(TNotifyUI& msg) = 0;
    };

    // MessageFilter interface
    class DUILIB_API IMessageFilterUI
    {
    public:
        virtual LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled) = 0;
    };

    class DUILIB_API ITranslateAccelerator
    {
    public:
        virtual LRESULT TranslateAccelerator(MSG* pMsg) = 0;
    };


    /////////////////////////////////////////////////////////////////////////////////////
    //
    typedef CControlUI* (*LPCREATECONTROL)(LPCTSTR pstrType);

    // 界面管理类
    class DUILIB_API CPaintManagerUI
    {
    public:
        CPaintManagerUI();
        ~CPaintManagerUI();

    public:
        // 初始化
        void Init(HWND hWnd, LPCTSTR pstrName = NULL);
        // 是否需要更新界面
        bool IsUpdateNeeded() const;
        // 当前需要更新界面
        void NeedUpdate();
        void Invalidate();
        void Invalidate(RECT& rcItem);

        // 获取对象标识
        LPCTSTR GetName() const;
        // 获取绘图DC
        HDC GetPaintDC() const;
        // RE：
        HBITMAP GetPaintOffscreenBitmap();
        // 获取绘图窗体句柄
        HWND GetPaintWindow() const;
        // 获取提示框句柄
        HWND GetTooltipWindow() const;
        // 获取提示框宽度
        int GetTooltipWindowWidth() const;
        // 设置提示框宽度
        void SetTooltipWindowWidth(int iWidth);
        // 获取Hover持续时间
        int GetHoverTime() const;
        // 设置Hover持续时间
        void SetHoverTime(int iTime);
        // 获取鼠标位置
        POINT GetMousePos() const;
        // 获取客户区位置
        SIZE GetClientSize() const;
        // 获取/设置 初始的窗体尺寸
        SIZE GetInitSize();
        void SetInitSize(int cx, int cy);
        // 获取/设置 尺寸调整框
        RECT& GetSizeBox();
        void SetSizeBox(RECT& rcSizeBox);
        // 获取/设置 标题栏尺寸
        RECT& GetCaptionRect();
        void SetCaptionRect(RECT& rcCaption);
        // 获取/设置 边框圆角
        SIZE GetRoundCorner() const;
        void SetRoundCorner(int cx, int cy);
        // 获取/设置 窗体最小尺寸
        SIZE GetMinInfo() const;
        void SetMinInfo(int cx, int cy);
        // 获取/设置 窗体最大尺寸
        SIZE GetMaxInfo() const;
        void SetMaxInfo(int cx, int cy);
        // Re: 获取/设置 刷新区域属性
        bool IsShowUpdateRect() const;
        void SetShowUpdateRect(bool show);
        // 获取/设置 无激活属性
        bool IsNoActivate();
        void SetNoActivate(bool bNoActivate);
        // 获取/设置 透明度属性
        BYTE GetOpacity() const;
        void SetOpacity(BYTE nOpacity);

        // 获取/设置 分层窗体属性
        bool IsLayered();
        void SetLayered(bool bLayered);
        // Re:
        RECT& GetLayeredInset();
        void SetLayeredInset(RECT& rcLayeredInset);
        // Re:
        BYTE GetLayeredOpacity();
        void SetLayeredOpacity(BYTE nOpacity);
        // Re:
        LPCTSTR GetLayeredImage();
        void SetLayeredImage(LPCTSTR pstrImage);

        // 获取应用程序句柄(HINSTANCE在win32下与HMODULE是相同的东西：应用程序载入的模块)
        static HINSTANCE GetInstance();
        // 获取应用程序所在的路径
        static CDuiString GetInstancePath();
        // 获取当前目录
        static CDuiString GetCurrentPath();
        // 获取资源DLL句柄
        static HINSTANCE GetResourceDll();
        // 获取资源文件目录
        static const CDuiString& GetResourcePath();
        // 获取资源包(Zip)路径
        static const CDuiString& GetResourceZip();
        // 是否缓存资源包句柄
        static bool IsCachedResourceZip();
        // 获取资源包(Zip)句柄
        static HANDLE GetResourceZipHandle();
        // 设置应用程序句柄
        static void SetInstance(HINSTANCE hInst);
        // 设置当前目录
        static void SetCurrentPath(LPCTSTR pStrPath);
        // 设置资源DLL句柄
        static void SetResourceDll(HINSTANCE hInst);
        // 设置资源文件目录
        static void SetResourcePath(LPCTSTR pStrPath);
        // 设置资源包(Zip)，通过内存对象
        static void SetResourceZip(LPVOID pVoid, unsigned int len);
        // 设置资源包(Zip)，通过路径
        static void SetResourceZip(LPCTSTR pstrZip, bool bCachedResourceZip = false);
        // 获取颜色（背景色？）
        static bool GetHSL(short* H, short* S, short* L);
        // 设置颜色（背景色？）
        static void SetHSL(bool bUseHSL, short H, short S, short L); // H:0~360, S:0~200, L:0~200
        // Re: 重新加载皮肤？
        static void ReloadSkin();
        // 获取界面管理对象
        static CPaintManagerUI* GetPaintManager(LPCTSTR pstrName);
        // 获取界面管理集合
        static CDuiPtrArray* GetPaintManagers();
        // 加载插件
        static bool LoadPlugin(LPCTSTR pstrModuleName);
        // 获取插件集合
        static CDuiPtrArray* GetPlugins();

        bool IsForceUseSharedRes() const;
        void SetForceUseSharedRes(bool bForce);

        DWORD GetDefaultDisabledColor() const;
        void SetDefaultDisabledColor(DWORD dwColor, bool bShared = false);
        DWORD GetDefaultFontColor() const;
        void SetDefaultFontColor(DWORD dwColor, bool bShared = false);
        DWORD GetDefaultLinkFontColor() const;
        void SetDefaultLinkFontColor(DWORD dwColor, bool bShared = false);
        DWORD GetDefaultLinkHoverFontColor() const;
        void SetDefaultLinkHoverFontColor(DWORD dwColor, bool bShared = false);
        DWORD GetDefaultSelectedBkColor() const;
        void SetDefaultSelectedBkColor(DWORD dwColor, bool bShared = false);

        TFontInfo* GetDefaultFontInfo();
        void SetDefaultFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic, bool bShared = false);
        DWORD GetCustomFontCount(bool bShared = false) const;
        HFONT AddFont(int id, LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic, bool bShared = false);
        HFONT GetFont(int id);
        HFONT GetFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);
        int GetFontIndex(HFONT hFont, bool bShared = false);
        int GetFontIndex(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic, bool bShared = false);
        void RemoveFont(HFONT hFont, bool bShared = false);
        void RemoveFont(int id, bool bShared = false);
        void RemoveAllFonts(bool bShared = false);
        TFontInfo* GetFontInfo(int id);
        TFontInfo* GetFontInfo(HFONT hFont);

        const TImageInfo* GetImage(LPCTSTR bitmap);
        const TImageInfo* GetImageEx(LPCTSTR bitmap, LPCTSTR type = NULL, DWORD mask = 0, bool bUseHSL = false);
        const TImageInfo* AddImage(LPCTSTR bitmap, LPCTSTR type = NULL, DWORD mask = 0, bool bUseHSL = false, bool bShared = false);
        const TImageInfo* AddImage(LPCTSTR bitmap, HBITMAP hBitmap, int iWidth, int iHeight, bool bAlpha, bool bShared = false);
        void RemoveImage(LPCTSTR bitmap, bool bShared = false);
        void RemoveAllImages(bool bShared = false);
        static void ReloadSharedImages();
        void ReloadImages();

        void AddDefaultAttributeList(LPCTSTR pStrControlName, LPCTSTR pStrControlAttrList, bool bShared = false);
        LPCTSTR GetDefaultAttributeList(LPCTSTR pStrControlName) const;
        bool RemoveDefaultAttributeList(LPCTSTR pStrControlName, bool bShared = false);
        void RemoveAllDefaultAttributeList(bool bShared = false);

        void AddWindowCustomAttribute(LPCTSTR pstrName, LPCTSTR pstrAttr);
        LPCTSTR GetWindowCustomAttribute(LPCTSTR pstrName) const;
        bool RemoveWindowCustomAttribute(LPCTSTR pstrName);
        void RemoveAllWindowCustomAttribute();

        CDuiString GetWindowAttribute(LPCTSTR pstrName);
        void SetWindowAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
        CDuiString GetWindowAttributeList(bool bIgnoreDefault = true);
        void SetWindowAttributeList(LPCTSTR pstrList);
        bool RemoveWindowAttribute(LPCTSTR pstrName);

        CDuiString GetWindowXML();

        // 多语言相关函数
        static void AddMultiLanguageString(int id, LPCTSTR pStrMultiLanguage);
        static LPCTSTR GetMultiLanguageString(int id);
        static bool RemoveMultiLanguageString(int id);
        static void RemoveAllMultiLanguageString();
        static void ProcessMultiLanguageTokens(CDuiString& pStrMultiLanguage);

        // UI界面相关
        bool AttachDialog(CControlUI* pControl);
        bool InitControls(CControlUI* pControl, CControlUI* pParent = NULL);
        bool RenameControl(CControlUI* pControl, LPCTSTR pstrName);
        void ReapObjects(CControlUI* pControl);

        // Re：TabControl？
        bool AddOptionGroup(LPCTSTR pStrGroupName, CControlUI* pControl);
        CDuiPtrArray* GetOptionGroup(LPCTSTR pStrGroupName);
        void RemoveOptionGroup(LPCTSTR pStrGroupName, CControlUI* pControl);
        void RemoveAllOptionGroups();

        // 焦点设置相关函数
        CControlUI* GetFocus() const;
        void SetFocus(CControlUI* pControl, bool bFocusWnd = true);
        void SetFocusNeeded(CControlUI* pControl);

        // Tab键焦点切换
        bool SetNextTabControl(bool bForward = true);

        // 定时器相关
        bool SetTimer(CControlUI* pControl, UINT nTimerID, UINT uElapse);
        bool KillTimer(CControlUI* pControl, UINT nTimerID);
        void KillTimer(CControlUI* pControl);
        void RemoveAllTimers();

        // 鼠标截获
        void SetCapture();
        void ReleaseCapture();
        bool IsCaptured();

        // 设置/获取绘图状态
        bool IsPainting();
        void SetPainting(bool bIsPainting);

        // 通知消息相关函数
        bool AddNotifier(INotifyUI* pControl);
        bool RemoveNotifier(INotifyUI* pControl);
        void SendNotify(TNotifyUI& Msg, bool bAsync = false, bool bEnableRepeat = true);
        void SendNotify(CControlUI* pControl, LPCTSTR pstrMessage, WPARAM wParam = 0, LPARAM lParam = 0, bool bAsync = false, bool bEnableRepeat = true);

        // 预消息过滤相关函数
        bool AddPreMessageFilter(IMessageFilterUI* pFilter);
        bool RemovePreMessageFilter(IMessageFilterUI* pFilter);

        // 消息过滤相关函数
        bool AddMessageFilter(IMessageFilterUI* pFilter);
        bool RemoveMessageFilter(IMessageFilterUI* pFilter);

        // 顶层控件绘制相关函数（PostPaint：绘制后处理）
        int GetPostPaintCount() const;
        bool AddPostPaint(CControlUI* pControl);
        bool RemovePostPaint(CControlUI* pControl);
        bool SetPostPaintIndex(CControlUI* pControl, int iIndex);

        // 本地窗体的绘制（有窗口句柄的控件）
        int GetNativeWindowCount() const;
        RECT GetNativeWindowRect(HWND hChildWnd);
        bool AddNativeWindow(CControlUI* pControl, HWND hChildWnd);
        bool RemoveNativeWindow(HWND hChildWnd);

        // 添加至延迟清理集合
        void AddDelayedCleanup(CControlUI* pControl);

        // 鼠标离开相关函数
        void AddMouseLeaveNeeded(CControlUI* pControl);
        bool RemoveMouseLeaveNeeded(CControlUI* pControl);

        // 快捷键相关函数
        bool AddTranslateAccelerator(ITranslateAccelerator* pTranslateAccelerator);
        bool RemoveTranslateAccelerator(ITranslateAccelerator* pTranslateAccelerator);
        bool TranslateAccelerator(LPMSG pMsg);

        CControlUI* GetRoot() const;
        CControlUI* FindControl(POINT pt) const;
        CControlUI* FindControl(LPCTSTR pstrName) const;
        CControlUI* FindSubControlByPoint(CControlUI* pParent, POINT pt) const;
        CControlUI* FindSubControlByName(CControlUI* pParent, LPCTSTR pstrName) const;
        CControlUI* FindSubControlByClass(CControlUI* pParent, LPCTSTR pstrClass, int iIndex = 0);
        CDuiPtrArray* FindSubControlsByClass(CControlUI* pParent, LPCTSTR pstrClass);

        // 消息循环
        static int MessageLoop();
        static bool TranslateMessage(const LPMSG pMsg);
        static void Term();

        // 消息处理函数
        bool MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes);
        // 消息预处理（在消息分派到窗体之前）
        bool PreMessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes);
        void UsedVirtualWnd(bool bUsed);

    private:
        CDuiPtrArray* GetFoundControls();
        static CControlUI* CALLBACK __FindControlFromNameHash(CControlUI* pThis, LPVOID pData);
        static CControlUI* CALLBACK __FindControlFromCount(CControlUI* pThis, LPVOID pData);
        static CControlUI* CALLBACK __FindControlFromPoint(CControlUI* pThis, LPVOID pData);
        static CControlUI* CALLBACK __FindControlFromTab(CControlUI* pThis, LPVOID pData);
        static CControlUI* CALLBACK __FindControlFromShortcut(CControlUI* pThis, LPVOID pData);
        static CControlUI* CALLBACK __FindControlFromName(CControlUI* pThis, LPVOID pData);
        static CControlUI* CALLBACK __FindControlFromClass(CControlUI* pThis, LPVOID pData);
        static CControlUI* CALLBACK __FindControlsFromClass(CControlUI* pThis, LPVOID pData);
        static CControlUI* CALLBACK __FindControlsFromUpdate(CControlUI* pThis, LPVOID pData);

        static void AdjustSharedImagesHSL();
        void AdjustImagesHSL();
        // 发送异步通知消息
        void PostAsyncNotify();

    private:
        // 对象标识
        CDuiString m_sName;
        // 绘图窗体句柄
        HWND m_hWndPaint = NULL;
        // 绘图DC
        HDC m_hDcPaint = NULL;
        HDC m_hDcOffscreen = NULL;
        HDC m_hDcBackground = NULL;
        HBITMAP m_hbmpOffscreen = NULL;
        COLORREF* m_pOffscreenBits = NULL;
        HBITMAP m_hbmpBackground = NULL;
        COLORREF* m_pBackgroundBits = NULL;
        int m_iTooltipWidth = -1;
        int m_iLastTooltipWidth = -1;
        // 提示框句柄
        HWND m_hwndTooltip = NULL;
        TOOLINFO m_ToolTip;
        // HOVER持续时间
        int m_iHoverTime = 1000;
        bool m_bNoActivate = false;
        bool m_bShowUpdateRect = false;
        // 记录消息相关的控件
        CControlUI* m_pRoot = NULL;
        CControlUI* m_pFocus = NULL;
        CControlUI* m_pEventHover = NULL;
        CControlUI* m_pEventClick = NULL;
        CControlUI* m_pEventKey = NULL;
        CControlUI* m_pLastToolTip = NULL;
        // 鼠标位置
        POINT m_ptLastMousePos;
        // 窗体最小尺寸
        SIZE m_szMinWindow;
        // 窗体最大尺寸
        SIZE m_szMaxWindow;
        // 窗体初始尺寸
        SIZE m_szInitWindowSize;
        // 尺寸调整框
        RECT m_rcSizeBox;
        // 边框圆角
        SIZE m_szRoundCorner;
        // 标题栏尺寸
        RECT m_rcCaption;
        UINT m_uTimerID = 0x1000;
        bool m_bFirstLayout = true;
        bool m_bUpdateNeeded = false;
        bool m_bFocusNeeded = false;
        bool m_bOffscreenPaint = true;

        BYTE m_nOpacity = 0xFF;
        bool m_bLayered = false;
        RECT m_rcLayeredInset;
        bool m_bLayeredChanged = false;
        RECT m_rcLayeredUpdate;
        TDrawInfo m_diLayered;

        bool m_bMouseTracking = false;
        bool m_bMouseCapture = false;
        bool m_bIsPainting = false;
        bool m_bUsedVirtualWnd = false;
        bool m_bAsyncNotifyPosted = false;

        // 集合
        CDuiPtrArray m_aNotifiers;      // 能够接收通知的对象集合
        CDuiPtrArray m_aTimers;         // 定时器集合
        CDuiPtrArray m_aPreMessageFilters;  // 预处理消息过滤器集合
        CDuiPtrArray m_aMessageFilters;     // 消息过滤器集合
        CDuiPtrArray m_aPostPaintControls;  // 发送绘制请求的控件集合
        CDuiPtrArray m_aNativeWindow;       // 本地窗体集合
        CDuiPtrArray m_aNativeWindowControl;
        CDuiPtrArray m_aDelayedCleanup; // 延迟清理的对象集合
        CDuiPtrArray m_aAsyncNotify;    // 异步通知消息集合
        CDuiPtrArray m_aFoundControls;
        CDuiPtrArray m_aNeedMouseLeaveNeeded;
        CDuiStringPtrMap m_mNameHash;
        CDuiStringPtrMap m_mWindowAttrHash;
        CDuiStringPtrMap m_mOptionGroup;

        // 
        bool m_bForceUseSharedRes = false;
        TResInfo m_ResInfo;

        //
        static HINSTANCE m_hResourceInstance;
        static CDuiString m_pStrResourcePath;
        static CDuiString m_pStrResourceZip;
        static HANDLE m_hResourceZip;

        static bool m_bCachedResourceZip;
        static TResInfo m_SharedResInfo;
        static HINSTANCE m_hInstance;
        static bool m_bUseHSL;
        static short m_H;
        static short m_S;
        static short m_L;
        // 消息预处理对象集合（实际上是CPaintManagerUI对象的集合）
        static CDuiPtrArray m_aPreMessages;
        // 插件集合
        static CDuiPtrArray m_aPlugins;

    public:
        // 快捷键分发集合
        CDuiPtrArray m_aTranslateAccelerator;
    };

} // namespace DuiLib

#endif // __UIMANAGER_H__
